﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FCS.GlobalComponents;
using System.Reflection;

namespace FCS.Emulator
{
    /// <summary>
    /// This represents the physical fountain and all of its states that are monitored by the cRIO.
    /// </summary>
    /// Values are stored in the
    /// same order that they arrive in the packets, from byte 0 to byte n, and from most to least significant bit. This order
    /// is mirrored in the cRIO Communication Protocol documentation.
    public class FountainState
    {
        public bool[] _horizontalValveStates = new bool[FountainConstants.SouthEndValveCountPerCaliper];
        public bool[] _verticalValveStates = new bool[FountainConstants.SouthEndValveCountPerCaliper];
        public bool[] _northValveStates = new bool[FountainConstants.NorthEndValveCount];
        public bool _northValveState;

        public bool _northMisterState, _southMisterState;
        public bool[] _lightStates = new bool[FountainConstants.LightCount];
        public bool[] _pumpVacuumStates = new bool[FountainConstants.PumpCount];
        public int _chassisTemperature;

        public bool[] _pumpStates = new bool[FountainConstants.PumpCount];
        public bool[] _bollardStates = new bool[FountainConstants.BollardCount];
        public bool[] _weirStates = new bool[FountainConstants.WeirCount];
        public bool[] _reportedEnvironStates = new bool[FountainConstants.ReportedEnvironmentalStates];
        public bool _windSensorState;

        /// <summary>
        /// Makes a value copy of a FountainState
        /// </summary>
        /// <returns>A FountainState with values identical to, but sharing no references, the source FountainState</returns>
        public FountainState DeepCopy()
        {
            FountainState stateToReturn = new FountainState();

            // Clone all of the value types
            stateToReturn = (FountainState)this.MemberwiseClone();
            // Clone all of the arrays. As awesome as C# is, I'm disappointed that there is no easy way to do this in one
            // shot. Maybe in the future, look into using FieldInfo and GetFields.
            stateToReturn._horizontalValveStates = (bool[])this._horizontalValveStates.Clone();
            stateToReturn._verticalValveStates = (bool[])this._verticalValveStates.Clone();
            stateToReturn._northValveStates = (bool[])this._northValveStates.Clone();
            stateToReturn._lightStates = (bool[])this._lightStates.Clone();
            stateToReturn._pumpVacuumStates = (bool[])this._pumpVacuumStates.Clone();
            stateToReturn._pumpStates = (bool[])this._pumpStates.Clone();
            stateToReturn._bollardStates = (bool[])this._bollardStates.Clone();
            stateToReturn._weirStates = (bool[])this._weirStates.Clone();
            stateToReturn._reportedEnvironStates = (bool[])this._reportedEnvironStates.Clone();

            // Good grief, finally done.
            return stateToReturn;
        }

        public override string ToString()
        {
            String ret = "";
            ret += "Horizontal Valve States: ";
            for (int i = 0; i < _horizontalValveStates.Length; i++)
                ret += (_horizontalValveStates[i] ? "1" : "0") + " ";

            ret += "\nVertical Valve States: ";
            for (int i = 0; i < _verticalValveStates.Length; i++)
                ret += (_verticalValveStates[i] ? "1" : "0") + " ";

            ret += "\nNorth Valve States: ";
            for (int i = 0; i < _northValveStates.Length; i++)
                ret += (_northValveStates[i] ? "1" : "0") + " ";

            ret += "\nNorth Tower State: " + _northValveState;

            ret += "\nNorth Mister State: " + _northMisterState + " South Mister State: " + _southMisterState;

            ret += "\nLight States: ";
            for (int i = 0; i < _lightStates.Length; i++)
                ret += (_lightStates[i] ? "1" : "0") + " ";

            ret += "\nPump Vacuum State: ";
            for (int i =0 ; i< _pumpVacuumStates.Length; i++)
                ret += (_pumpVacuumStates[i] ? "1" : "0") + " ";

            ret += "\neRIO Chassis Temp: " + _chassisTemperature;

            ret += "\nPump States: ";
            for (int i =0; i < _pumpStates.Length; i++)
                ret += (_pumpStates[i] ? "1" : "0") + " ";

            ret += "\nBollard States";
            for (int i =0; i < _bollardStates.Length; i++)
                ret += (_bollardStates[i] ? "1" : "0") + " ";

            ret += "\nWeir States";
            for (int i =0; i< _weirStates.Length; i++)
                ret += (_weirStates[i] ? "1" : "0") + " ";

            ret += "\nEnvrion States\n";
            ret += "North disable: " + (_reportedEnvironStates[0] ? "1" : "0") + "\n";
            ret += "South disable: " + (_reportedEnvironStates[1] ? "1" : "0") + "\n";
            ret += "Side walk OK: " + (_reportedEnvironStates[2] ? "1" : "0") + "\n";
            ret += "Manhole closed: " + (_reportedEnvironStates[3] ? "1" : "0") + "\n";

            ret += "\nWind Sensor State: " + (_windSensorState ? "1" : "0");

            return ret;
        }
    }
}
